namespace Resharper.Abstractions.CodeDom.Expressions.CastOperatorExpressions
{
  using System.Diagnostics;
  using JetBrains.Annotations;
  using JetBrains.ReSharper.Psi.CSharp.Tree;
  using Resharper.Abstractions.CodeDom.Expressions.LiteralExpressions;

  /// <summary>Defines the <see cref="LiteralExpression"/> class.</summary>
  public class CastOperatorExpression : Expression
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="LiteralExpression"/> class.</summary>
    /// <param name="catExpression">The expression.</param>
    internal CastOperatorExpression([NotNull] ICastExpression catExpression) : base(catExpression)
    {
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the right operand.
    /// </summary>
    [CanBeNull]
    public Expression Operand
    {
      get
      {
        var expression = this.InternalCastExpression.Op;
        if (expression == null)
        {
          return null;
        }

        return ExpressionFactory.GetExpression(expression);
      }
      set
      {
        Debug.Assert(value != null, "value != null");

        this.InternalCastExpression.SetOp((IUnaryExpression)value.InternalExpression);
      }
    }

    /// <summary>The literal expression field.</summary>
    [NotNull]
    internal ICastExpression InternalCastExpression
    {
      get
      {
        return (ICastExpression)this.InternalExpression;
      }
    }

    /// <summary>
    /// Gets the type operand.
    /// </summary>
    [NotNull]
    public string TypeOperand
    {
      get
      {
        var typeOperand = this.InternalCastExpression.TargetType;
        if (typeOperand == null)
        {
          return string.Empty;
        }

        return typeOperand.GetText();
      }
    }

    #endregion

    #region Public Methods

    /// <summary>
    /// Gets the operator sign text range.
    /// </summary>
    public bool OperatorContains(int offset)
    {
      var operand = this.InternalCastExpression.Op;
      if (operand == null)
      {
        return true;
      }

      var range = operand.GetNavigationRange();

      return !range.TextRange.Contains(offset);
    }

    #endregion
  }
}